/*
 * Board.cpp
 *
 *  Created on: 10 déc. 2011
 *      Author: Elca
 */

#include "BoardInfos.hpp"
#include <cstring>

namespace pcm {

LL BoardInfos::cons = 0;

 short int BoardInfos::m_gameNumberHole = 0;
 short int BoardInfos::m_gameSize = 0;
HolePosition* BoardInfos::m_holePosition = NULL;
vector<HoleJump>*  BoardInfos::m_startHoleJumps = NULL;
vector<HoleJump>*  BoardInfos::m_endHoleJumps = NULL;

BoardInfos::BoardInfos() {
	//cons++;
	m_board=0;
	m_numberPeg=0;
	m_numberJoin=0;
}

BoardInfos::~BoardInfos() {
	//cons--;
}

void BoardInfos::fillBoard(){
	m_numberPeg = gameNumberHole();
	for(short int hole=0;hole<gameNumberHole();hole++){
		setHole(hole,true);
	}
}

void BoardInfos::updateGameInfos(short int gameSize){
	setGameSize(gameSize);
	setGameNumberHole(gameSize);
}

void BoardInfos::printBoard() const{
	cout << "Board size:"<<gameSize()<< "#hole:"<<gameNumberHole()<<" #peg:"<<numberPeg()<<" #join:"<<numberJoin()<<endl;
	for(short int lign=0;lign<gameSize();lign++){
		cout.width(gameSize()-lign);
		for(short int col=0;col<=lign;col++){
			cout << hole(lign,col)<< " ";
		}
		cout <<endl;
	}
}
void BoardInfos::printJumps() const{
	cout << "Holes jumps:"<<endl;
	short int i = 0;
	cout <<"Start:"<<endl;
	for(short int iStartHole=0;iStartHole<gameNumberHole();iStartHole++){
		vector<HoleJump> jumps = startHoleJumps(iStartHole);
		for(size_t iJumps=0;iJumps<jumps.size();iJumps++){
			cout.width(4);
			cout <<i;
			cout<<": "<< jumps.at(iJumps)<<endl;
			i++;
		}
	}
	i=0;
	cout << "End:"<<endl;
	for(short int iEndHole=0;iEndHole<gameNumberHole();iEndHole++){
		vector<HoleJump> jumps = endlHoleJumps(iEndHole);
		for(size_t iJumps=0;iJumps<jumps.size();iJumps++){
			cout.width(4);
			cout <<i;
			cout<<": "<< jumps.at(iJumps)<<endl;
			i++;
		}
	}
}
void BoardInfos::printHolePos() const{
	cout <<"Holes position:"<<endl;
	for(short int iHole;iHole<gameNumberHole();iHole++){
		cout << holePosition(iHole)<<endl;
	}
}
void BoardInfos::calculateHolesPos(){
	if(m_holePosition!=NULL){
		delete[] m_holePosition;
	}
	m_holePosition = new HolePosition[gameNumberHole()];
	short int nHole;
	for(short int lign=0;lign<gameSize();lign++){
		for(short int col=0;col<=lign;col++){
			nHole = HolePosition::convToHoleNumber(lign,col);
			m_holePosition[nHole].updatePost(lign,col);
		}
	}
}

void BoardInfos::calculateHolesJumps(){

	if(m_startHoleJumps != NULL){
		delete[] m_startHoleJumps;
	}
	m_startHoleJumps = new vector<HoleJump>[gameNumberHole()];
	if(m_endHoleJumps != NULL){
		delete[] m_endHoleJumps;
	}
	m_endHoleJumps = new vector<HoleJump>[gameNumberHole()];

	for(short int iHole=0;iHole<gameNumberHole();iHole++){
		const HolePosition& holePos = holePosition(iHole);
		vector<HoleJump> jumps;

		//Check 6 directions
		if(holePos.lign()>1){
			if(holePos.col()<holePos.lign()-1){
				//NE (l-1, c),(l-2, c)
				HoleJump ne(iHole,
							HolePosition::convToHoleNumber(holePos.lign()-1,holePos.col()),
							HolePosition::convToHoleNumber(holePos.lign()-2,holePos.col()));
				m_startHoleJumps[iHole].push_back(ne);
				m_endHoleJumps[ne.end()].push_back(ne);
				//E (l,c+1),(l,c+2)
				HoleJump e( iHole,
							HolePosition::convToHoleNumber(holePos.lign(),holePos.col()+1),
							HolePosition::convToHoleNumber(holePos.lign(),holePos.col()+2));
				m_startHoleJumps[iHole].push_back(e);
				m_endHoleJumps[e.end()].push_back(e);
			}
			if(holePos.col()>1){
				//NW (l-1,c-1),(l-2,c-2)
				HoleJump nw(iHole,
							HolePosition::convToHoleNumber(holePos.lign()-1,holePos.col()-1),
							HolePosition::convToHoleNumber(holePos.lign()-2,holePos.col()-2));
				m_startHoleJumps[iHole].push_back(nw);
				m_endHoleJumps[nw.end()].push_back(nw);
				//W	(l,c-1),(l,c-2)
				HoleJump w( iHole,
							HolePosition::convToHoleNumber(holePos.lign(),holePos.col()-1),
							HolePosition::convToHoleNumber(holePos.lign(),holePos.col()-2));
				m_startHoleJumps[iHole].push_back(w);
				m_endHoleJumps[w.end()].push_back(w);
			}
		}
		if(holePos.lign()<gameSize()-2){
			//SE (l+1,c+1),(l+2,c+2)
			if(holePos.col()<gameSize()-2){
				HoleJump se(iHole,
							HolePosition::convToHoleNumber(holePos.lign()+1,holePos.col()+1),
							HolePosition::convToHoleNumber(holePos.lign()+2,holePos.col()+2));
				m_startHoleJumps[iHole].push_back(se);
				m_endHoleJumps[se.end()].push_back(se);
			}
			//SW (l+1,c),(l+2,c)
			HoleJump sw(iHole,
						HolePosition::convToHoleNumber(holePos.lign()+1,holePos.col()),
						HolePosition::convToHoleNumber(holePos.lign()+2,holePos.col()));
			m_startHoleJumps[iHole].push_back(sw);
			m_endHoleJumps[sw.end()].push_back(sw);
		}
	}
}
void BoardInfos::initBoard(short int holeToRemove){
	m_numberJoin = 0;
	fillBoard();
	setHole(holeToRemove,false);
	decrementNumberPeg();
	incrementNumberJoin();
	calculateHolesPos();
	calculateHolesJumps();
}

} /* namespace pcm */
